﻿/**************************************************************
 * Copyright gt1987. All rights reserved.
 * 
 * Author: guitao(guitao@eastmoney.com) 
 * Create Date: 2020/5/12 13:51:07
 * Description: TaskSchedulerLeaderProvider
 *          
 * Revision History:
 *      Date         Author               Description
 *              
***************************************************************/

using gt.TaskScheduler.Core.Components;
using log4net;
using log4net.Util;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace gt.TaskScheduler.Core.Impl
{
    public class TaskSchedulerLeaderProvider : ITaskSchedulerLeaderProvider
    {
        private IDistributeFeature _distribute;
        private IKeyBuilder _keyBuilder;

        public TaskSchedulerLeaderProvider(IDistributeFeature distribute, IKeyBuilder keyBuilder)
        {
            _distribute = distribute;
            _keyBuilder = keyBuilder;
        }

        /// <summary>
        /// 尝试生成任务调度Leader。
        /// 一个集群只能有1个Leader
        /// TODO：依赖ditributeFeature 过期时间。一旦过期，此时一个新增的节点启动，会变为主节点，则此时，集群中会有2个主节点
        /// </summary>
        /// <param name="memberName">集群任务调度名称</param>
        /// <returns>非空，则表示当前member为Leader。</returns>
        public ITaskSchedulerLeader TryCreateLeader(string memberName, ITaskSchedulerMananger manager)
        {
            ITaskSchedulerLeader leader = null;

            if (manager.CheckTaskSchedulerCanStart())
            {
                var lockKey = _keyBuilder.GetLockKey();
                var lockValue = Guid.NewGuid().ToString("n");
                try
                {
                    if (_distribute.GetLock(lockKey, lockValue))
                    {
                        leader = new TaskSchedulerLeader(memberName, manager);
                    }
                }
                catch (Exception ex)
                {
                    leader = null;
                    LogHelper.GetLogger().Error(ex);
                }
                finally
                {
                    _distribute.ReleaseLock(lockKey, lockValue);
                }
            }

            return leader;
        }
    }
}
